#include <mutex>
#include <functional>
#include <condition_variable>

using namespace std;

class ZeroEvenOdd
{
private:
    int n = 40;
    mutex m;
    condition_variable con;
    bool flag = true;
    int cou = 1;
public:
    // printNumber(x) outputs "x", where x is an integer.
    void zero(function<void(int)> printNumber)
    {
        while (cou <= n)
        {
            unique_lock<mutex> Lock(m);
            con.wait(Lock, [&]()
                     { return flag; });
            if (cou <= n)
            {
                printNumber(0);
            }
            flag = false;
            con.notify_all();
        }
    }

    void even(function<void(int)> printNumber)
    {
        while (cou <= n)
        {
            unique_lock<mutex> Lock(m);
            con.wait(Lock, [&]()
                     { return !flag && cou % 2; });
            if (cou <= n)
            {
                printNumber(cou);
                ++cou;
            }
            flag = true;
            con.notify_all();
        }
    }

    void odd(function<void(int)> printNumber)
    {
        while (cou <= n)
        {
            unique_lock<mutex> Lock(m);
            con.wait(Lock, [&]()
                     { return !flag && cou % 2 == 0; });
            if (cou <= n)
            {
                printNumber(cou);
                ++cou;
            }
            flag = true;
            con.notify_all();
        }
    }
};